package tech.yunland.shop.domain.service;

import com.moyuer.bsf.domain.dao.UserDao;
import com.moyuer.bsf.domain.model.HqlArgs;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.yunland.shop.domain.dao.*;
import tech.yunland.shop.domain.model.ChargeBill;
import tech.yunland.shop.domain.model.ChargeBillEntry;
import tech.yunland.shop.domain.model.GoodsPackage;
import tech.yunland.shop.domain.model.GoodsPackageEntry;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 充值类
 *
 * @author 王睿智<geekrize@gmail.com>
 */
@Service
public class ChargeBillService {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	private static final String DELETE_ENTRIES_HQL = "delete from ChargeBillEntry cbe where cbe.owner.id=?";

	@Autowired
	private ChargeBillDao chargeBillDao;
	@Autowired
	private SNGenerator snGenerator;
	@Autowired
	private ChargeBillEntryDao chargeBillEntryDao;
	@Autowired
	private GoodsPaidDao goodsPaidDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private IncomeDao incomeDao;
	@Autowired
	private CommissionDao commissionDao;
	@Autowired
	private GoodsPackageDao goodsPackageDao;


	/**
	 * 新增充值单
	 *
	 * @param chargeBill
	 *            对象
	 * @return void
	 */
	public void add(ChargeBill chargeBill) {
		chargeBill.setSn(snGenerator.gen("charge", chargeBill.getOrganId()));
		chargeBillDao.saveOrUpdate(chargeBill);
		//TODO 是不是可以 设置级联保存
		if (chargeBill.getEntries() != null) {
			for (ChargeBillEntry chargeBillEntry : chargeBill.getEntries()) {
				chargeBillEntryDao.saveOrUpdate(chargeBillEntry);
			}
		}
	}

	/**
	 * 生效充值单
	 *
	 * @param id  充值单单据ID
	 */
	public void validate(String id) {
 		ChargeBill bill = chargeBillDao.get(id);

		bill.setState(1); // 生效状态
		chargeBillDao.update(bill);

//		BigDecimal rate = this.getGoodsPrize(bill);
		BigDecimal rate = BigDecimal.ZERO;
		int rateSize = bill.getReceivable().compareTo(bill.getReceived());
		if(rateSize==0){
			rate = new BigDecimal(1);
		}else{
			rate = bill.getReceived().divide(bill.getReceivable(), 2, BigDecimal.ROUND_HALF_UP);
		}

		// 将充值数据计入收入报表
 		incomeDao.addCharge(bill.getOrganId(), bill.getBizdate(),bill.getReceived());

		for (ChargeBillEntry chargeBillEntry : bill.getEntries()) {
			GoodsPackage goodsPackage = goodsPackageDao.get(chargeBillEntry.getGoodsPackage().getId());
			for(GoodsPackageEntry goodsPackageEntry:goodsPackage.getEntries()){
				if (bill.getMember() != null) {

					BigDecimal quantity = goodsPackageEntry.getQuantity().multiply(chargeBillEntry.getQuantity());

					BigDecimal amount = goodsPackageEntry.getPrice().multiply(quantity).multiply(rate);

					//将充值数据计入预购报表
					goodsPaidDao.add(bill.getOrganId(), bill.getMemberId(),goodsPackageEntry.getGoods().getId(), quantity,amount);
				} else {
					throw new RuntimeException("单据异常：请选择会员！");
				}
			}
		}
	}


	/**
	 * 充值单测试
	 * @param bill
     */
	public void test(ChargeBill bill){

		// 将充值数据计入收入报表
		incomeDao.addCharge(bill.getOrganId(), bill.getBizdate(),bill.getReceived());
		for (ChargeBillEntry chargeBillEntry : bill.getEntries()) {
			GoodsPackage goodsPackage = goodsPackageDao.get(chargeBillEntry.getGoodsPackage().getId());
			for(GoodsPackageEntry goodsPackageEntry:goodsPackage.getEntries()){
					//将充值数据计入预购报表
					goodsPaidDao.add(bill.getOrganId(), bill.getMemberId(),goodsPackageEntry.getGoods().getId(), goodsPackageEntry.getQuantity(),goodsPackageEntry.getPrice().multiply(goodsPackageEntry.getQuantity()));

			}
		}

	}


	/**
	 * 新增充值单,并直接生效
	 *
	 * @param bill
	 */
	public void addAndValidate(ChargeBill bill) {
		add(bill);
		validate(bill.getId());
	}

	/**
	 * 根据 id 标记删除 chargeBill
	 *
	 * @param id
	 *            唯一标识符
	 * @return void
	 */
	@Transactional
	public void delete(String id) {
		ChargeBill chargeBill = chargeBillDao.get(id);

		if (chargeBill.getState() != -1) {
			chargeBill.setState(-1);
		} else {
			throw new RuntimeException("该充值单据已删除");
		}

		chargeBillDao.update(chargeBill);
	}

	/**
	 * 根据 id 读取表单
	 *
	 * @param id
	 *            唯一标识符
	 * @return ChargeBill 对象
	 */
	public ChargeBill get(String id) {
		return chargeBillDao.get(id);
	}

	/**
	 * 根据 id 读取表单详情
	 *
	 * @param id
	 * @return
	 */
	public ChargeBillEntry getCBE(String id) {
		return chargeBillEntryDao.get(id);
	}

	/**
	 * 根据参数生成 hql 语句 chargeBill
	 *
	 * @param param
	 *            sn
	 * @param states
	 *            状态
	 * @param creatorIds
	 *            创建 id
	 * @param organIds
	 *            组织 id
	 * @return
	 */
	private HqlArgs genHqlArgs(String param, List<Integer> states,String[] creatorIds, List<String> organIds) {
		param = StringUtils.trimToEmpty(param);

		Map<String, Object> args = new HashMap<String, Object>();

		String hql = "from ChargeBill cb where 1=1";
		if (StringUtils.isNotBlank(param)) {
			hql += " and (cb.sn like :arg or cb.remark like :arg)";
			args.put("arg", "%" + param + "%");
		}

		if (states != null && states.size() > 0) {
			if (states.size() == 1) {
				hql += " and cb.state=:states";
				args.put("states", states.get(0));
			} else {
				hql += " and cb.state in :states";
				args.put("states", states);
			}
		}

		if (organIds != null && organIds.size() > 0) {
			if (organIds.size() == 1) {
				hql += " and cb.organ.id = :organIds";
				args.put("organIds", organIds.get(0));
			} else {
				hql += " and cb.organ.id in :organIds";
				args.put("organIds", organIds);
			}
		}

		if (creatorIds != null) {
			if (creatorIds.length == 1) {
				hql += " and cb.creator.id = :creatorIds";
				args.put("creatorIds", creatorIds);
			} else {
				hql += " and cb.creator.id in :creatorIds";
				args.put("creatorIds", creatorIds);
			}
		}

		return new HqlArgs(hql, args);
	}

	/**
	 * 根据参数生成 hql 语句 chargeBillEntry
	 *
	 * @param ownerId
	 * @param goodsPackageId
	 * @return
	 */
	private HqlArgs genHqlArgsCBE(String ownerId, String goodsPackageId) {

		Map<String, Object> args = new HashMap<String, Object>();

		String hql = "from ChargeBillEntry cbe where 1=1";
		if (ownerId != null) {
			hql += " and cbe.ownerId = ownerId";
			args.put("owerId", ownerId);
		}

		if (goodsPackageId != null) {
			hql += "and cbe.goodsPackage_id = goodsPackageId";
			args.put("goodsPackageId", goodsPackageId);
		}

		return new HqlArgs(hql, args);
	}

	/**
	 * 根据入参查询结果数量 chargeBill
	 *
	 * @param param sn
	 * @param states 状态
	 * @param creatorIds 创建 id
	 * @param organIds 组织 id
	 * @return int 结果数量
	 */
	public int getResultSize(String param, List<Integer> states,String[] creatorIds, List<String> organIds) {
		HqlArgs hqlArgs = genHqlArgs(param, states, creatorIds, organIds);

		return (int) chargeBillDao.getCount(hqlArgs.getHql(),hqlArgs.getArgs());
	}


	/**
	 * 根据入参查询结果数量 chargeBillEntry
	 *
	 * @param ownerId
	 * @param goodsPackageId
	 * @return
	 */
	public int getResultSizeCBE(String ownerId, String goodsPackageId) {
		HqlArgs hqlArgs = genHqlArgsCBE(ownerId, goodsPackageId);

		return chargeBillEntryDao.findByNamedParam(hqlArgs.getHql(),hqlArgs.getArgs()).size();
	}

	/**
	 * 根据入参查询结果集 chargeBill
	 *
	 * @param param
	 *            sn
	 * @param states
	 *            状态
	 * @param creatorIds
	 *            创建 id
	 * @param startIndex
	 *            开始位置
	 * @param length
	 *            长度
	 * @param organIds
	 *            组织 id
	 * @return ChargeBill 结果集
	 */
	public List<ChargeBill> getResultInfos(String param, List<Integer> states,String[] creatorIds, Integer startIndex, Integer length,List<String> organIds) {
		HqlArgs hqlArgs = genHqlArgs(param, states, creatorIds, organIds);
		String hql = "select cb " + hqlArgs.getHql() + " order by cb.sn desc";

		return chargeBillDao.findByNamedParam(hql, startIndex, length,hqlArgs.getArgs());

	}

	/**
	 * 根据入参查询结果集 chargeBillEntry
	 *
	 * @param ownerId
	 * @param goodsPackageId
	 * @param startIndex
	 * @param length
	 * @return
	 */

	public List<ChargeBillEntry> getResultInfoCBE(String ownerId,String goodsPackageId, Integer startIndex, Integer length) {
		HqlArgs hqlArgs = genHqlArgsCBE(ownerId, goodsPackageId);
		String hql = "select cbe " + hqlArgs.getHql();

		return chargeBillEntryDao.findByNamedParam(hql, startIndex, length,hqlArgs.getArgs());
	}


	///////////////////////////////////////////////////////////////////////////////////////////////////////
	public List<ChargeBill> getAllChargeBill(){
		String hql = "from ChargeBill cb where cb.state=?";
		return chargeBillDao.find(hql,1);
	}

}
